package com.mmq.ets.modele;
/******************************************************
Cours:  LOG121
Projet: Squelette du laboratoire #1
Nom du fichier: CommBase.java
Date créé: 2013-05-03
*******************************************************
Historique des modifications
*******************************************************
*@author Patrice Boucher
2013-05-03 Version initiale
*******************************************************/  

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Observable;

import javax.swing.SwingWorker;

import com.mmq.ets.util.Labo2Const.ProprietesChangees;

/**
 * Base d'une communication via un fil d'exécution parallèle.
 */
public class CommBase extends Observable 
{
	
	private final int DELAI = 10;
	private SwingWorker threadComm =null;
	private boolean actif = false;
	private Socket connectionClient;
	
	private BufferedReader inputStream;
	private PrintWriter outputStream;
	private GestionaireFormes gestionaireFormes;
	/**
	 * Constructeur par défaut
	 */
	public CommBase()
	{
	}
	
	
	/**
	 * D�finir le r�cepteur de l'information re�ue dans la communication avec le serveur
	 * @param listener sera alerté lors de l'appel de "firePropertyChanger" par le SwingWorker
	 */
	public CommBase(GestionaireFormes gestionaire)
	{
		gestionaireFormes=gestionaire;
	}
	
	/**
	 * Démarre la communication
	 */
	public void start(){
		actif=true;
		creerCommunication();
	}
	
	/**
	 * Arrête la communication
	 */
	public void stop(){
		if(threadComm!=null)
			threadComm.cancel(true); 
		actif = false;
	}
	
	/**
	 *  Il crée la communication avec un serveur. Pour ce faire, il démarre un fils d'execution paralléle. 
	 *  Ce dernier recevra et traitera la definition d'une forme.  
	 */
	protected void creerCommunication()
	{		
		// Crée un fil d'exécusion parallèle au fil courant,
		threadComm = new SwingWorker(){
			@Override
			protected Object doInBackground() throws IOException, InterruptedException{
				System.out.println("Le fils d'execution parallele est lance");
					//Configurations avec le serveur
					inputStream= new BufferedReader((new InputStreamReader(connectionClient.getInputStream())));
					outputStream=new PrintWriter(new OutputStreamWriter(connectionClient.getOutputStream()));
					int compteurLocal=0;
					while(gestionaireFormes.getListeFigures().taille()<10)
					{	
						Thread.sleep(DELAI);
							outputStream.println("GET");
							outputStream.flush();
							if (inputStream.read()!=0)
							{
							
								String temp=inputStream.readLine();
								temp=inputStream.readLine();
								//Si la communication s'arrête, on notifie la vue et on arrête le processus
								if(temp==null)
								{
									CommBase.this.setChanged();						
									CommBase.this.notifyObservers(ProprietesChangees.SERVEUR_TOMBE);	
									break;				
								}
								System.out.println(temp);
								//Ajoute d'une forme
								gestionaireFormes.ajouterForme(temp);
								compteurLocal++;
							}
										
					}
					
				threadComm=null;
				CommBase.this.fermerConnexion();
				return null;
				
			}
			
		}; 		
		threadComm.execute(); // Lance le fil d'exécution parallèle.
		actif = true;
		
//		outputStream.close();
	}
	
	/**
	 * @return si le fil d'exécution parallèle est actif
	 */
	public boolean isActif(){
		return actif;
	}
	/**
	 * @return La connexion du client
	 */
	public Socket getConnexionClient() {
		return connectionClient;
	}
	/**
	 * @return le fil d'exécution parallèle
	 */
	public SwingWorker getThreadComm() {
		return threadComm;
	}
	/**
	 * Fermeture de la connexion de façon sécuritaire 
	 */
	public void fermerConnexion() 
	{ 
		if(connectionClient!=null)
		{
			actif = false;
			try 
		    {
				outputStream=new PrintWriter(new OutputStreamWriter(connectionClient.getOutputStream()));
			} 
			catch (IOException e1)
			{
				e1.printStackTrace();
			}
			outputStream.println("END");
			outputStream.flush();
			outputStream.close();
			if(inputStream!=null)
			{
				try 
				{
					inputStream.close();
				} 
				catch (IOException e) 
				{
					e.printStackTrace();
				}
			}
			try 
			{
				connectionClient.close();
				connectionClient=null;
			} 
			catch (IOException e)
			{
				
				e.printStackTrace();
			}
			finally
			{
				threadComm=null;
			}

		}	
	}
	
	/**
	 * Ouverture d'une connexion.
	 * @param paramConnection
	 * La connexion ne se fait:
	 * -Lorsque le port n'est pas un nombre entier
	 * -Losrqu'il y a un erreur dans l'addresse.
	 * -Lorsque le serveur ne réponds pas sur l'addresse donnée
	 */
	public void ouvrirConnexion(String[] paramConnection)
	{
		
			int port;
			try
			{
				port=Integer.parseInt(paramConnection[1]);	
			}
			catch(NumberFormatException e)
			{
				//Notification à la vue 
				this.setChanged();
				this.notifyObservers(ProprietesChangees.ERREUR_NO_INT);
				return;
			}
			InetSocketAddress sockAdress=new InetSocketAddress(paramConnection[0],port);
			if(sockAdress.isUnresolved())
			{
				//Notification à la vue 
				this.setChanged();
				this.notifyObservers(ProprietesChangees.ERREUR_DNS);
				return;
			}
			try 
			{
				connectionClient = new Socket(sockAdress.getHostName(),sockAdress.getPort());
			} 
			catch (UnknownHostException e) 
			{
				//Notification à la vue 
				this.setChanged();
				this.notifyObservers(ProprietesChangees.CONNECTION_REFUSE);
				return;
			} 
			catch (IOException e) 
			{	
				//Notification à la vue 
				String[] paramsErreur={ProprietesChangees.CONNECTION_REFUSE.toString(),sockAdress.getHostName(),sockAdress.getPort()+""};
				this.setChanged();
				this.notifyObservers(paramsErreur);
				return;
			}
			if(connectionClient!=null)
			{
				//Notification à la vue 
				this.gestionaireFormes.getListeFigures().toutSupprimer();
				this.setChanged();
				this.notifyObservers(ProprietesChangees.CONNECTION_REUSSIE);
			}
	
		
	}


}
